<script setup lang="ts">
import { useRoute } from 'vue-router'
import { Message, Notification } from '@arco-design/web-vue'
import { useDateFormat, useEventBus, useNow, useStorage, useTitle } from '@vueuse/core'
import notificationTpl from '~/pages/template/notification.vue'
import { WebSocketClient } from '~/utils/useWebSocket'
import content from '~/pages/message.vue'
import configs from '~/config'
import user from '~/pages/user.vue'
import type { InsertMessage, SocketStatus } from '~/pages/types'

const audioRef = ref<any>()
const alertRef = ref<any>()
const webSocket = ref<any>()
const userRef = ref<any>()
const messageRef = ref<any>()
const myself = ref<any>('')
const route = useRoute()
const talkList: any = useStorage('talk_list', [])
const socketStatus = ref<SocketStatus>('loading')
const receiveMessage = ref<any>()
const socketUrl: string = (process.env.NODE_ENV === 'development'
  ? ENV.BASE.API_DEV.SOCKET
  : ENV.BASE.API_PROD.SOCKET)
const talkData = ref<any>()
const reLoad = ref<boolean>(false)

const { on } = useEventBus('message-bus')
const eventData = ref<any>()
// 监听eventBus事件总线程
on(async (eventMessage) => {
  eventData.value = eventMessage

  // 监听到内容进行判断

  // sendMessage 发送消息
  if (eventData.value.type === 'sendMessage') {
    // 页面插入信息
    await webSocket.value?.send(JSON.stringify(eventData.value.params))
    // 发送成功后，进行页面插入
    const { from, to } = eventData.value.params
    const insertMessage: InsertMessage = {
      createTime: useDateFormat(useNow(), 'YYYY-MM-DD HH:mm:ss'),
      fromUser: from,
      toUser: to,
      isRead: false,
      messageType: 'MESSAGE',
      text: JSON.stringify(eventData.value.params.context),
    }
    messageRef.value.insertToChat(insertMessage)
    // 将页面置底部
    nextTick(() => {
      messageRef.value.scrollToBottom()
    })
  }
})

function createWebSocket() {
  const ws = new WebSocketClient(`${socketUrl}?token=${route.query?.token}`)
  webSocket.value = ws
  ws.connect()
  ws.onopen(() => {
    socketStatus.value = 'connect'
    Notification.success({
      title: '通知',
      id: 'notify',
      content: '消息连接已建立',
    })
  })

  // 收到消息
  ws.onmessage((event: MessageEvent) => {
    // 接受到消息后进行解析
    if (event.data) {
      const message = JSON.parse(event.data)

      if (message.messageResultType === 'MESSAGE') {
        alertRef.value.tips(`用户消息通知`, message.result.text, message.result.talkId)
        audioRef.value.play()
        // 根据当前接受到的消息进行判断
        const talkUser = talkList.value.find((item: any) => item.id === message.result.talkId)
        if (talkUser) {
          talkUser.lastTalkMessage = message.result.text
        }
        else {
          // 如果没有找到，则说明当前对话不存在，重新请求一下列表信息
          userRef.value?.fetchTalkInfo()
        }

        // 回复消息
        if (message.result)
          receiveMessage.value = message.result
      }

      if (message.messageResultType === 'OFFLINE') {
        Notification.error({
          title: `通知`,
          id: 'notify',
          duration: 0,
          content: `当前账户已下线`,
        })
      }
    }
  })

  ws.onclose(() => {
    socketStatus.value = 'close'
    Notification.error({
      title: `通知`,
      id: 'notify',
      content: `当前账户已下线`,
    })
  })

  ws.onerror((event: ErrorEvent) => {
    socketStatus.value = 'close'
    Message.error('网络连接发生错误', event.error)
  })
}

// 跳转到聊天页面
function navigateToTalk(id: string) {
  const talkUser = talkList.value.find((item: any) => item.id === id)
  if (talkUser)
    takeTalk(talkUser)
}

function handleSendMessage(val: any) {
  webSocket.value?.send(JSON.stringify(val))
}

// 进行对话
function takeTalk(data: any) {
  talkData.value = data
  const talk = useStorage('talk_detail', data)
  talk.value = data
}

function init() {
  useTitle(configs.TITLE)
  const token = route.query?.token
  if (token) {
    // 存储token
    const token = useStorage('token', route.query?.token)
    token.value = route.query?.token
    createWebSocket()

    Message.info({
      id: 'openSound',
      content: '关闭此弹窗即可开启声音提示',
      closable: true,
      duration: 0,
    })
  }
  else {
    Message.error('当前没有登录信息，请重新登录')
  }
}

onMounted(() => {
  // 获取当前用户信息
  const user = useStorage('user', '')
  if (user.value)
    myself.value = JSON.parse(user.value)
  init()

  // 监听页面切换
  document.addEventListener('visibilitychange', () => {
    if (document.visibilityState === 'hidden') {
      // 切离该页面时执行
      reLoad.value = true
    }
    else if (document.visibilityState === 'visible') {
      // 切换到该页面时执行
      reLoad.value = false
      localStorage.removeItem('user')
    }
  })
})
</script>

<template>
  <audio v-show="false" ref="audioRef" preload="auto" controls>
    <source src="/static/talk.mp3" type="audio/mp3">
  </audio>

  <div v-if="!reLoad">
    <notificationTpl ref="alertRef" @click="navigateToTalk" />
    <div h-full flex flex-j-c flex-a-c>
      <div h-full w-full flex rounded-20px bg-white color-black>
        <user ref="userRef" :status="socketStatus" box-border min-w-320px border-r-1px @talk="takeTalk" />
        <content
          ref="messageRef" :status="socketStatus" class="content-panel" :receive="receiveMessage" :res="talkData"
          @send="handleSendMessage"
        />
      </div>
    </div>
  </div>
</template>

<style scoped>
.content-panel {
  width: calc(100vw - 320px);
}
</style>
